#include "Ordenador_Archivo.h"
#include "Constantes.h"
//#include "CompresorDelta.h"
#include <sstream>
#include <iostream>

Ordenador_Archivo::Ordenador_Archivo() {
}

int Ordenador_Archivo::mezcla_natural(std::fstream *terminos,
		std::string nom_arch) {
	std::fstream arch_aux1(nom_arch_aux1,
			std::fstream::in | std::fstream::out | std::fstream::trunc);
	std::fstream arch_aux2(nom_arch_aux2,
			std::fstream::in | std::fstream::out | std::fstream::trunc);
	std::string linea, linea_anterior;
	bool primera_linea = true;
	unsigned char archivo = 0;
	// Mezcla natural ordeno de a pedazos

	// Separo el archivo de a paquetes
	while (getline(*terminos, linea)) {
		//std::cout << linea << std::endl;
		if (!primera_linea) {
			if (linea.compare(linea_anterior.c_str()) >= 0) {
				//std::cout << "linea_anterior < linea" << std::endl;
			}
			if (linea.compare(linea_anterior.c_str()) < 0) {
				//std::cout << "linea_anterior > linea" << std::endl;
				archivo++;
			}
			if (archivo == 2)
				archivo = 0;
			linea_anterior = linea;
			linea += '\n';
			switch (archivo % 2) {
			case 0:
				arch_aux1 << linea;
				break;
			case 1:
				arch_aux2 << linea;
				break;
			}
		} else {
			primera_linea = false;
			linea_anterior = linea;
			linea += '\n';
			arch_aux1 << linea;
		}
	}

	if (arch_aux2.tellp() == 0) {
		//std::cout << "Ordenado" << std::endl;
		return 0;
	}

	arch_aux1.seekg(0, std::ios_base::beg);
	arch_aux2.seekg(0, std::ios_base::beg);

	terminos->close();
	terminos->open(nom_arch.c_str(),
			std::fstream::trunc | std::fstream::out | std::fstream::in);

	std::string linea1, linea2;
	getline(arch_aux1, linea1);
	getline(arch_aux2, linea2);
	bool fin = false, primer_termino = true;
	while (!fin) {
		//std::cout << "linea1:" << linea1 << std::endl;
		//std::cout << "linea2:" << linea2 << std::endl;
		/*if(arch_aux2.eof()) {
		 std::cout<< "FIN de archivo 2" << std::endl;
		 getchar();
		 }
		 if(arch_aux1.eof()) {
		 std::cout<< "FIN de archivo 1" << std::endl;
		 getchar();
		 }*/
		//if((linea1.compare("nueva") == 0) || (linea2.compare("nueva") == 0))
		//getchar();
		//std::cout << terminos->fail() << std::endl;
		//std::cout << linea1.size() << "   " << linea2.size() << std::endl;
		//getchar();
		if (primer_termino) {
			if (linea1.compare(linea2.c_str()) < 0) {
				//std::cout << "PRIMER T 1" << std::endl;
				linea_anterior = linea1;
				linea1 += '\n';
				*terminos << linea1;
				linea1.clear();
				getline(arch_aux1, linea1);
			} else {
				if (linea1.compare(linea2.c_str()) > 0) {
					//std::cout << "PRIMER T 2" << std::endl;
					linea_anterior = linea2;
					linea2 += '\n';
					*terminos << linea2;
					linea2.clear();
					getline(arch_aux2, linea2);
				} else {
					if (linea1.compare(linea2.c_str()) == 0) {
						//std::cout << "PRIMER T 3" << std::endl;
						linea_anterior = linea1;
						linea1 += '\n';
						*terminos << linea1;
						*terminos << linea1;
						linea1.clear();
						linea2.clear();
						getline(arch_aux1, linea1);
						getline(arch_aux2, linea2);
					}
				}
			}
			primer_termino = false;
		} else {
			while ((comparar_strings(linea1, linea2, linea_anterior) == 0)
					&& (linea1.size() > 0)) {
				//getchar();
				//std::cout << "Linea1:" << linea1 << std::endl;
				linea_anterior = linea1;
				linea1 += '\n';
				*terminos << linea1;
				linea1.clear();
				getline(arch_aux1, linea1);
				primer_termino = false;
			}
			while ((comparar_strings(linea1, linea2, linea_anterior) == 1)
					&& (linea2.size() > 0)) {
				//std::cout << "Linea2:" << linea2 << std::endl;
				linea_anterior = linea2;
				linea2 += '\n';
				*terminos << linea2;
				linea2.clear();
				getline(arch_aux2, linea2);
				primer_termino = false;
			}
			while ((comparar_strings(linea1, linea2, linea_anterior) == 2)
					&& (linea2.size() > 0) && (linea1.size() > 0)) {
				//std::cout << "linea 1 y 2 " << linea1 << std::endl;
				linea_anterior = linea1;
				linea1 += '\n';
				linea2 += '\n';
				*terminos << linea2;
				*terminos << linea1;
				linea1.clear();
				linea2.clear();
				getline(arch_aux1, linea1);
				getline(arch_aux2, linea2);
				primer_termino = false;
			}
		}
		if ((linea1.size() == 0) && (linea2.size() == 0))
			fin = true;
	}
	if (!esta_ordenado(terminos))
		mezcla_natural(terminos, nom_arch);
	arch_aux1.clear();
	arch_aux2.clear();
	arch_aux1.close();
	arch_aux2.close();
	//getchar();
	//std::cout << "Ordenado 2" << std::endl;
	return 0;
}

// Chequeo si el archivo ya esta ordenado
bool Ordenador_Archivo::esta_ordenado(std::fstream *archivo) {
	//std::cout << "Viendo ordenamiento" << std::endl;
	archivo->seekg(0, std::ios_base::beg);
	std::string linea, linea_anterior;
	bool primer_lectura = true, ordenado = true;
	while ((getline(*archivo, linea)) && (ordenado)) {
		//std::cout << "Leido " << linea << std::endl;
		if (!primer_lectura) {
			if (linea_anterior.compare(linea.c_str()) > 0)
				ordenado = false;
		} else
			primer_lectura = false;
		linea_anterior = linea;
	}
	archivo->clear();
	archivo->seekg(0, std::ios_base::beg);
	return ordenado;
}

// Ret = 0 linea1 mas cercano a linea_anterior, Ret = 1 escribir linea2, Ret = 2 ambos
int Ordenador_Archivo::comparar_strings(std::string linea1, std::string linea2, std::string linea_anterior) {
	int aux1 = linea_anterior.compare(linea1.c_str());
	int aux2 = linea_anterior.compare(linea2.c_str());
	int aux3 = linea1.compare(linea2.c_str());
	int aux4 = linea1.size();
	int aux5 = linea2.size();
	unsigned char ret = 0;
	if ((aux1 < 0) && (aux2 < 0)) {
		if (aux3 > 0) {
			ret = 1;
			//std::cout << "escribo 'linea2' en el archivo y linea_anterior = linea2" << std::endl;
		}
		if (aux3 < 0) {
			ret = 0;
			//std::cout << "escribo 'linea1' en el archivo y linea_anterior = linea1" << std::endl;
		}
		if (aux3 == 0) {
			ret = 2;
			//std::cout << "escribo ambos y linea_anterior = linea1/2" << std::endl;
		}
	} else {
		// Como ya comprobe que si es menor q las 2, entrara a un solo if o a ninguno
		if (aux2 < 0) {
			ret = 1;
			//std::cout << "escribo 'linea2' en el archivo y linea_anterior = linea2" << std::endl;
		}
		if (aux1 < 0) {
			ret = 0;
			//std::cout << "escribo 'linea1' en el archivo y linea_anterior = linea1" << std::endl;
		}
	}

	// Si la linea_anterior es mayor que las otras dos, me fijo cual de las lineas es mas chica
	if ((aux1 > 0) && (aux2 > 0)) {
		if ((aux4 > 0) && (aux5 > 0)) {
			if (aux3 < 0) {
				ret = 0;
				//std::cout << "escribo 'linea1' en el archivo y linea_anterior = linea1" << std::endl;
			}
			if (aux3 > 0) {
				ret = 1;
				//std::cout << "escribo 'linea2' en el archivo y linea_anterior = linea2" << std::endl;
			}
			if (aux3 == 0) {
				ret = 2;
				//std::cout << "escribo ambos y linea_anterior = linea1/2" << std::endl;
			}
		} else {
			if (aux4 > 0) {
				ret = 0;
				//std::cout << "escribo 'linea1' en el archivo y linea_anterior = linea1" << std::endl;
			}
			if (aux5 > 0) {
				ret = 1;
				//std::cout << "escribo 'linea2' en el archivo y linea_anterior = linea2" << std::endl;
			}
		}
	} else {
		// Como ya comprobe que si es mayor q las 2, entrara a un solo if o a ninguno
		if (aux2 > 0) {
			ret = 0;
			//std::cout << "escribo 'linea1' en el archivo y linea_anterior = linea1" << std::endl;
		}
		if (aux1 > 0) {
			ret = 1;
			//std::cout << "escribo 'linea2' en el archivo y linea_anterior = linea2" << std::endl;
		}
	}
	if ((aux1 == 0) && (aux2 == 0)) {
		ret = 2;
		//std::cout << "escribo ambos y linea_anterior = linea1/2" << std::endl;
	} else {
		if (aux1 == 0) {
			ret = 0;
			//std::cout << "escribo 'linea1' en el archivo y linea_anterior = linea1" << std::endl;
		}
		if (aux2 == 0) {
			ret = 1;
			//std::cout << "escribo 'linea2' en el archivo y linea_anterior = linea2" << std::endl;
		}
	}
	return ret;
}

Ordenador_Archivo::~Ordenador_Archivo() {}
